package top.xzxsrq.fileviewutils.security;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.jsonwebtoken.Claims;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import top.xzxsrq.fileviewutils.entity.SysUserWithRole;
import top.xzxsrq.fileviewutils.entity.TokensAreDiscarded;
import top.xzxsrq.fileviewutils.mapper.TokensAreDiscardedMapper;
import top.xzxsrq.web.utils.AjaxResult;
import top.xzxsrq.web.utils.JwtTokenUtil;
import top.xzxsrq.web.utils.WebUtils;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 用于授权
 */
public class JWTAuthorizationFilter extends BasicAuthenticationFilter {

    private TokensAreDiscardedMapper tokensAreDiscardedMapper;

    public JWTAuthorizationFilter(AuthenticationManager authenticationManager,TokensAreDiscardedMapper tokensAreDiscardedMapper) {
        super(authenticationManager);
        this.tokensAreDiscardedMapper=tokensAreDiscardedMapper;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        String tokenHeader = request.getHeader(JwtTokenUtil.TOKEN_HEADER);
        if (tokenHeader == null) { // 从请求参数上再获取一次
            tokenHeader = request.getParameter(JwtTokenUtil.TOKEN_HEADER);
        }
        // 若请求头中没有Authorization信息 或是Authorization不以Bearer开头 则直接放行
        if (tokenHeader == null || !tokenHeader.startsWith(JwtTokenUtil.TOKEN_PREFIX)) {
            chain.doFilter(request, response);
            return;
        }
        // 去掉前缀 获取Token字符串
        String token = tokenHeader.replace(JwtTokenUtil.TOKEN_PREFIX, "");
        Claims claims = JwtTokenUtil.checkJWT(token);
        if (claims == null) {
            WebUtils.renderString(response, AjaxResult.failure("token异常"));
            return;
        }
        // 校验是否过期
        boolean expiration = JwtTokenUtil.isExpiration(token);
        if (expiration) {
            WebUtils.renderString(response, AjaxResult.failure("token过期"));
            return;
        }
        // 从Token中解密获取用户名
        SysUserWithRole sysUser = JwtTokenUtil.getSysUser(token);
        if (sysUser == null) {
            WebUtils.renderString(response, AjaxResult.failure("用户信息丢失"));
            return;
        }
        LambdaQueryWrapper<TokensAreDiscarded> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TokensAreDiscarded::getToken,token);
        TokensAreDiscarded tokensAreDiscarded = tokensAreDiscardedMapper.selectOne(queryWrapper);
        if(tokensAreDiscarded != null) {
            WebUtils.renderString(response, AjaxResult.failure("token过期"));
            return;
        }
        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(sysUser, null, sysUser.getAuthorities());
        // 若请求头中有token 则调用下面的方法进行解析 并设置认证信息
        SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
        super.doFilterInternal(request, response, chain);
    }
}
